package com.jishuo.nontax.bfc.tlq;

import com.jishuo.base.config.NonTaxConfig;
import com.jishuo.base.service.SequenceService;
import com.jishuo.nontax.bean.message.HBFSBodyDTO;
import com.jishuo.nontax.bean.message.HBFSDTO;
import com.jishuo.nontax.bean.message.HBFSHeadDTO;
import com.jishuo.nontax.bean.vo.MessageVO;
import com.jishuo.nontax.bfc.ca.JDCA;
import com.jishuo.nontax.bfc.dao.MessageSysMapper;
import com.jishuo.nontax.bfc.service.*;
import org.simpleframework.xml.Serializer;
import org.simpleframework.xml.core.Persister;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.StringReader;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 消息服务，财政交互
 *
 * @author jhb
 */
@Service
public class MessageService {
    private static Logger logger = LoggerFactory.getLogger(MessageService.class);
    @Resource
    private JmsSender jmsSender;
    @Resource
    private NonTaxConfig nonTaxConfig;
    @Resource
    private JDCA jdca;
    @Resource
    private ParameterService parameterService;
    @Resource
    private SequenceService sequenceService;
    @Resource
    @Lazy
    private EticketNumService eticketNumService;
    @Resource
    private MessageSysMapper messageSysMapper;
    @Resource
    @Lazy
    private FiscService fiscService;
    @Resource
    @Lazy
    private BackBillService backBillService;
    @Resource
    @Lazy
    private PayScaleBillService payScaleBillService;
    @Resource
    @Lazy
    private DivideService divideService;
    @Resource
    @Lazy
    private SpecialService specialService;
    @Resource
    @Lazy
    private PunishService punishService;
    @Resource
    @Lazy
    private ChargeBillService chargeBillService;
    @Resource
    @Lazy
    private IllegalactivityinfoService illegalactivityinfoService;
    @Resource
    @Lazy
    private StudentService studentService;
    @Resource
    @Lazy
    private WaitaffirmService waitaffirmService;
    @Resource
    @Lazy
    private BaseDataService baseDataService;
    @Resource
    @Lazy
    private BankCheckService bankCheckService;
    @Resource
    @Lazy
    private EpayFiscService epayFiscService;

    @Resource
    private BackMessageService backMessageService;

    private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    private SimpleDateFormat sdfDay = new SimpleDateFormat("yyyyMMdd");
    private final String xmlDeclare = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";

    /**
     * 发送消息，并等待财政返回。用于单据查询
     *
     * @param msgType   消息类型
     * @param messageid id序号
     * @param objInfo   请求数据，用于生成报文
     * @param ver       消息版本
     * @return
     * @throws Exception
     */
    public boolean sendAndRecvMessage(String msgType, long messageid, Object objInfo, String ver) throws Exception {
        if (CertAndQueue.CACERTID == null) {
            parameterService.selectFselecertandqueue();
        }
        //xml解析器
        Serializer serializer = new Persister();
        //xml转换器
        StringWriter sw = new StringWriter();
        serializer.write(objInfo, sw);
        String orgdata = sw.toString();

        String rom = Integer.toString(new Random().nextInt(CertAndQueue.TLQQUEUE.size()));
        String sn = nonTaxConfig.Sender + sdfDay.format(new Date()) + "-" + messageid;
        HBFSDTO hbfs = getHBFS(ver, msgType, "1", orgdata, rom, sn);

        sw = new StringWriter();
        serializer.write(hbfs, sw);
        String hbfsMsg = sw.toString();

        String filepath = jmsSender.sendData(CertAndQueue.TLQQUEUE.get(rom), this.xmlDeclare + hbfsMsg, hbfs.getHead().getSn());
        logger.info("发送到财政   " + msgType + "   日期:" + sdf.format(new Date()) + "  SN: " + hbfs.getHead().getSn());
        //保存发送记录
        messageSysMapper.saveMessageSend(messageid, orgdata, hbfsMsg, CertAndQueue.TLQQUEUE.get(rom), filepath,
                ver, hbfs.getHead().getSender(), hbfs.getHead().getReceiver(), msgType, hbfs.getHead().getBillcount(),
                hbfs.getHead().getSn(), 0, sdf.format(new Date()), hbfs.getBody().getSignmessage());

        for (int i = 0; i < 30; i++) {
            if (backMessageService.getSn(hbfs.getHead().getSn())) return true;
            Thread.sleep(1500); // 休眠1.5秒
        }
        logger.info("查询票据超时。action=" + msgType + "，sn=" + hbfs.getHead().getSn());
        return false;
    }

    /**
     * 发送消息
     *
     * @param msgType   消息类型
     * @param messageid id序号
     * @param objInfo   请求数据，用于生成报文
     * @param ver       消息版本
     * @return
     * @throws Exception
     */
    public boolean sendMessage(String msgType, long messageid, Object objInfo, String ver) throws Exception {
        if (CertAndQueue.CACERTID == null) {
            parameterService.selectFselecertandqueue();
        }
        //xml解析器
        Serializer serializer = new Persister();
        //xml转换器
        StringWriter sw = new StringWriter();
        serializer.write(objInfo, sw);
        String orgdata = sw.toString();

        String rom = Integer.toString(new Random().nextInt(CertAndQueue.TLQQUEUE.size()));
        HBFSDTO hbfs = getHBFS(ver, msgType, "1", orgdata, rom, UUID.randomUUID().toString());
        sw = new StringWriter();
        serializer.write(hbfs, sw);
        String hbfsMsg = sw.toString();

        String filepath = jmsSender.sendData(CertAndQueue.TLQQUEUE.get(rom), this.xmlDeclare + hbfsMsg, null);

        //保存发送记录
        messageSysMapper.saveMessageSend(messageid, orgdata, hbfsMsg, CertAndQueue.TLQQUEUE.get(rom), filepath,
                ver, hbfs.getHead().getSender(), hbfs.getHead().getReceiver(), msgType, hbfs.getHead().getBillcount(),
                hbfs.getHead().getSn(), 0, sdf.format(new Date()), hbfs.getBody().getSignmessage());

        return true;
    }


    public void receiveMessageTask(){
        try{
            logger.info("启动定时分析接收数据");
            // 删除超过3天的消息
            Calendar cal = Calendar.getInstance();
            cal.add(Calendar.DAY_OF_YEAR, -3);
            String ft = new SimpleDateFormat("yyyy-MM-dd").format(cal.getTime());
            messageSysMapper.deleteDateMessage(ft);
            List<MessageVO> list = messageSysMapper.getEleMessageList();
            for(MessageVO mess:list){
                String temp=new String(mess.getHbfs().getBytes());
                if(!temp.equals("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"))
                {
                    receiveMessage(mess.getReceivequeue(),mess.getMsgid(),mess.getHbfs(),mess.getFilepath());
                }
            }
            messageSysMapper.deleteDateMessageSend(ft);
            List<MessageVO> eleMessageSendList = messageSysMapper.getEleMessageSendList();
            for(MessageVO mess:eleMessageSendList){
                if(!mess.getHbfs().equals("")) {
                    jmsSender.sendData(mess.getReceivequeue(), this.xmlDeclare + new String(mess.getHbfs().getBytes()), null);
                    messageSysMapper.updateMessageSendStateOne(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()),mess.getMessageid());
                }
            }
            logger.info("结束定时分析接收数据");
        }catch(Exception e){
            logger.info("数据分析失败"+e.toString());
        }
    }

    /**
     * 接收消息
     *
     * @param queue    队列
     * @param msgid    消息id
     * @param message  消息报文
     * @param filepath
     */
    public void receiveMessage(String queue, String msgid, String message, String filepath) {
        if (CertAndQueue.CACERTID == null) {
            parameterService.selectFselecertandqueue();
        }
        //查询发送方的合法性
        if (CertAndQueue.RECEIVEQUEUE.get(queue) == null) {
            logger.info(queue + "队列接收到未配置的发送方消息,消息ID：" + msgid);
            return;
        }

        try {
            // 保存消息，新建
            long messageid = sequenceService.getNextSeq("ELEMESSAGESEQ");
            String curDate = sdf.format(new Date());
            messageSysMapper.saveMessageReceive(messageid, message, queue, msgid, filepath, curDate, 0);
            // 转换消息为DTO
            Serializer serializer = new Persister();
            HBFSDTO hbfs = serializer.read(HBFSDTO.class, new StringReader(message));

            // 判断消息结构和银行类别是否正常
            if (hbfs == null || hbfs.getHead() == null || hbfs.getHead().getSender() == null || hbfs.getHead().getSender().trim().equals("")) {
                logger.info("解析消息失败,返回出错消息" + message);
                messageSysMapper.updateMessageReceiveFinish(messageid, 3, curDate);
                return;
            }

            //
            int state = 1;
            String info = (hbfs.getHead().getInfo() == null) ? "" : hbfs.getHead().getInfo().trim();
            String data = null;
            if (hbfs.getBody() != null && hbfs.getBody().getMessage() != null) {
                data = jdca.decodeEnvelop(hbfs.getBody().getMessage(), hbfs.getHead().getIsencrypt());
                if (data == null) {
                    data = "";
                    state = 4;
                    logger.info("消息解密失败,消息ID：" + msgid);
                } else {
                    if (!jdca.verifySignMessage(hbfs.getBody().getSignmessage(), data, hbfs.getHead().getIsencrypt())) {
                        state = 5;
                        logger.info("消息验签失败,消息ID：" + msgid);
                    }
                }
            }

            String action = (hbfs.getHead().getAction() == null) ? "" : hbfs.getHead().getAction().trim();
            // 保存业务数据消息
            messageSysMapper.updateMessageReceive(messageid, (data == null) ? "" : data, hbfs.getHead().getVersion(), hbfs.getHead().getSender(),
                    hbfs.getHead().getReceiver(), action, hbfs.getHead().getBillcount(), hbfs.getHead().getSn(), info, state, curDate);

            if (state != 1) {
                return;
            }

            // 报文业务处理
            boolean finishMsg = true; // 是否更新发送表
            if ("REPLY".equals(action)) {
//                //发送报文
//                HBFSDTO hbfs1 = new HBFSDTO();
//                //组织报文头
//                HBFSHeadDTO hbfshead1 = new HBFSHeadDTO();
//                hbfshead1.setVersion("2.0");
//                hbfshead1.setSn(hbfs.getHead().getSn());
//                hbfshead1.setSender(hbfs.getHead().getReceiver());
//                hbfshead1.setReceiver(hbfs.getHead().getSender());
//                hbfshead1.setAction("REPLY");
//                hbfshead1.setBillcount("0");
//                hbfshead1.setIsencrypt(hbfs.getHead().getIsencrypt());
//                hbfshead1.setInfo("INFO_9011_1");
//                hbfs1.setHead(hbfshead1);
//
//                //返回报文
//                StringWriter sw = new StringWriter();
//                serializer.write(hbfs1, sw);
//
//                jmsSender.sendData(CertAndQueue.RECEIVEQUEUE.get(queue), this.xmlDeclare + sw.toString(), null);
            } else if ("SETETICKETNUM".equals(action)) { //电子缴款书
                int billstate = InfoCode.getEticketNumCode(info);
                eticketNumService.setEticketNum(data, billstate, hbfs.getHead().getSn());
            }else if("SETPAYFISC".equals(action)){// 国库
                int billstate = InfoCode.getPayFiscCode(info);

                String version = hbfs.getHead().getVersion();
                if( "2.0".equals(version) ){
                    fiscService.setPayFisc(data,billstate,hbfs.getHead().getSn());
                }
                else if( "2.4".equals(version) ){
                    fiscService.setPayFiscNew(data,billstate,hbfs.getHead().getSn());
                }
            } else if ("SETILLEGALACTIVITYSCALE".equals(action)) {//交管二八分成
                int billstate = InfoCode.getIllegalactivityScaleCode(info);
                payScaleBillService.setIllegalactivityScale(data);
            }else if("SETPAYDIVIDE".equals(action)){ // 分成
                int payDivideCode = InfoCode.getPayDivideCode(info);
                String version = hbfs.getHead().getVersion();
                if( "2.0".equals(version) ){
                    divideService.setPayDivide(data,payDivideCode,hbfs.getHead().getSn());
                }
                else if( "2.4".equals(version) ){
                    divideService.setPayDivideNew(data,payDivideCode,hbfs.getHead().getSn());
                }
            } else if ("SETCHARGEBILLISACTIVE".equals(action)) { // 验证手工缴款书
                int billstade = InfoCode.getChargeBillCode(info);
                chargeBillService.updateChargeBillIsActivestate(billstade,hbfs.getHead().getSn());
            }else if("SETBACKBILL".equals(action)){
                int billstate = InfoCode.getBackBillCode(info);
                backBillService.setBackBill(data,billstate,hbfs.getHead().getSn());
            } else if("SETCHARGEBILL".equals(action)){
                int billstate = InfoCode.getChargeBillTwoCode(info);
                chargeBillService.setChargeBill(data,billstate,hbfs.getHead().getSn());
            }else if("SETPAYSPECIAL".equals(action)){ // 划解分成
                int paySpecialCode = InfoCode.getPaySpecialCode(info);
                String version = hbfs.getHead().getVersion();
                if( "2.0".equals(version) ){
                    specialService.setPaySpecial(data,paySpecialCode,hbfs.getHead().getSn());
                }
                else if( "2.4".equals(version) ){
                    specialService.setPaySpecialNew(data,paySpecialCode,hbfs.getHead().getSn());
                }
            } else if ("SETLATEFEE".equals(action)) {  //滞纳金
                int billstate = InfoCode.getPunishStateInfoCode(info);
                punishService.setLatefee(data, billstate, hbfs.getHead().getSn());
            } else if ("SETILLEGALACTIVITYINFO".equals(action)) {  // 交罚决定书
                int billstate = InfoCode.getIllegalactivityInfoCode(info);
                illegalactivityinfoService.setIllegalactivityInfo(data, billstate, hbfs.getHead().getSn());
            }else if ("SETSTUDENT".equals(action)) {  // 学生缴费
                int billstate = InfoCode.getStudentCOde(info);
                studentService.setStudent(data, billstate, hbfs.getHead().getSn());
            }else if("SENDREGETWAITAFFIRM".equals(action)){ // 返回财政已对账待查
                String version = hbfs.getHead().getVersion();
                if( "2.0".equals(version) ){
                    waitaffirmService.sendRegetWaitaffirm(data, info, hbfs.getHead().getSn());
                }
                else if( "2.2".equals(version) ){
                    waitaffirmService.sendRegetNewWaitaffirm(data, info, hbfs.getHead().getSn());
                }
                else{
                    logger.info(" SENDREGETWAITAFFIRM no version : " + version);
                }
            }else if("GETCANTON".equals(action)){
                baseDataService.sysSETCANTON(data);
                finishMsg = false;
            }else if("GETBANK".equals(action)){
                String version = hbfs.getHead().getVersion();
                if( "2.0".equals(version) ){
                    baseDataService.sysSETBANKS(data);
                }
                else if( "2.3".equals(version) ){
                    baseDataService.sysSETBANK(data);
                }else{
                    //
                    System.out.println(" GETBANK no version : " + version);
                }
            }else if("GETUNIT".equals(action)){
                baseDataService.sysSETUNIT(data);
            }else if("GETBASEUNIT".equals(action)){
                baseDataService.sysSETUNIT(data);
            }else if("GETITEM".equals(action)){
                //保存项目信息
                String version = hbfs.getHead().getVersion();
                if( "2.0".equals(version) ){
                    baseDataService.sysSETITEM(data);
                }
                else if( "2.3".equals(version) ){
                    baseDataService.sysNEWITEM(data);
                }
                else{
                    logger.info(" GETITEM no version : " + version);
                }
            }else if("GETUNITVSITEM".equals(action)){
                baseDataService.sysSETUNITVSITEM(data);
            }else if("GETBILLTYPE".equals(action)){
                baseDataService.sysSETBILLTYPE(data);
                finishMsg = false;
            } else if("GETKEYWORD".equals(action)){
                baseDataService.sysSETKEYWORD(data);
                finishMsg = false;
            }else if("GETPAYWAY".equals(action)){
                baseDataService.sysSETPAYWAY(data);
                finishMsg = false;
            }else if("GETPAYERTYPE".equals(action)){
                baseDataService.sysSETPAYERTYPE(data);
                finishMsg = false;
            }else if("SETPREERR".equals(action)){
                bankCheckService.sysSETPREERR(data);
                finishMsg = false;
            }else if("SETPREERRDETAIL".equals(action)){
                bankCheckService.sysSETPREERRDETAIL(data);
                finishMsg = false;
            }else if("SETCHECKDATACOUNT".equals(action)){   //201806新增
//                bankCheckService.sysSETCHECKDATACOUNT(data);
                finishMsg = false;
            }else if("SETCHECKDATALIST".equals(action)){   //201806新增
//                bankCheckService.sysSETCHECKDATALIST(data);
                finishMsg = false;
            }else if("SETPAYINFO".equals(action)){ // ???????????
                int illegalactivityInfoCode = InfoCode.getIllegalactivityInfoCode(info);
                punishService.updateIllegalactivitySendState(hbfs.getHead().getSn(),illegalactivityInfoCode);
                finishMsg = false;
            }else if("SETILLEGALACTIVITYCROSSPAYINFO".equals(action)){ // ??????????
                int illegalactivityInfoCode = InfoCode.getIllegalactivityInfoCode(info);
                punishService.updateIllegalactivitySendState(hbfs.getHead().getSn(),illegalactivityInfoCode);
                finishMsg = false;
            }else if("SETILLEGALACTIVITYSCALEINFO".equals(action)){
                payScaleBillService.setIllegalactivityScale(data);
            }else if(hbfs.getHead().getAction().trim().equals("GETREALBANKBALANCE")){
                // 电子缴库，获取账户实时余额，2023-10-24
                epayFiscService.getBankBalance(hbfs);
                finishMsg = false;
            } else {
                finishMsg = false;
            }
            if (finishMsg) this.finishMessageSend(hbfs.getHead().getSn(), curDate);
            messageSysMapper.updateMessageReceiveFinish(messageid, 2, curDate);
        } catch (Exception e) {
            logger.info("解析财政报文失败。" + message, e);
        }
    }

    /**
     * 收到返回数据后，更新消息发送表
     *
     * @param sn
     */
    private void finishMessageSend(String sn, String finishtime) {
        messageSysMapper.updateMessageSendFinish(sn, 2, finishtime);
        backMessageService.setMsg(sn);
    }

    // 生成消息对象
    private HBFSDTO getHBFS(String version, String action, String infocount, String message, String rom, String sn) {
        String isencrypt = CertAndQueue.ISENCRYPT.get(rom);
        //发送报文
        HBFSDTO hbfs = new HBFSDTO();
        //组织报文头
        HBFSHeadDTO hbfshead = new HBFSHeadDTO();
        hbfshead.setVersion(version);
        hbfshead.setSn(sn);
        hbfshead.setSender(nonTaxConfig.Sender);
        hbfshead.setReceiver(nonTaxConfig.Receiver);
        hbfshead.setAction(action);
        hbfshead.setBillcount(infocount);
        hbfshead.setIsencrypt(isencrypt);
        hbfshead.setInfo("");
        hbfs.setHead(hbfshead);
        //组织报文体
        HBFSBodyDTO hbfsbody = new HBFSBodyDTO();
        //加密数据
        hbfsbody.setMessage(jdca.encodeEnvelop(message, CertAndQueue.CACERTID.get(rom), isencrypt));
        hbfsbody.setSignmessage(jdca.signMessage(message, CertAndQueue.SIGNCACERTID.get(rom), isencrypt));
        hbfs.setBody(hbfsbody);
        return hbfs;
    }
}
